package com.chinatelecom.ifree.business.util.redis;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.chinatelecom.ifree.business.configcenter.helper.NutcrackerHelper;

import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;

/**
 * shardedredis pool 线程安全 单例工具类
 * 
 * @author haoxw
 * @since 2014/4/14
 */
public class NutcrackerCenter {
	public static final Logger logger = LoggerFactory.getLogger(NutcrackerCenter.class);
	private static NutcrackerCenter instance = null;
	public static String REDIS_SERVERS = null;

	private NutcrackerCenter() {
	}

	/**
	 * 实例化服务池
	 * 
	 * @param zkPath
	 *            内容是该节点下配置的nutcracker服务列表
	 * @return
	 */
	public synchronized static NutcrackerCenter getInstance() {
		if (instance == null) {
			instance = new NutcrackerCenter();
			instance.initialPool();
		}
		return instance;
	}

	private int MAX_ACTIVE = 512;
	private int MAX_IDLE = 256;
	private int MAX_WAIT = 5120;
	private int TIME_OUT = 3000;
	private boolean TEST_ON_BORROW = true;
	private boolean TEST_WHILE_IDLE = false;
	/**
	 * 公用redis集群 共享资源池
	 */
	private ShardedJedisPool shardCommonPool = null;

	/**
	 * 初始化redis 池
	 * 
	 * @param path
	 */
	public void initialPool() {
		try {
			REDIS_SERVERS = NutcrackerHelper.getInstance().getNutURL();
			List<JedisShardInfo> listJedisShardInfo = new ArrayList<JedisShardInfo>();
			String serverArray[] = REDIS_SERVERS.split("[,]");
			JedisShardInfo jsi = null;
			String redisInfo[] = null;
			for (String server : serverArray) {
				redisInfo = server.split("[:]");
				jsi = new JedisShardInfo(redisInfo[0], Integer.parseInt(redisInfo[1].toString()), TIME_OUT);
				listJedisShardInfo.add(jsi);
			}
			JedisPoolConfig config = new JedisPoolConfig();
			config.setMaxTotal(MAX_ACTIVE);
			config.setMaxIdle(MAX_IDLE);
			config.setMaxWaitMillis(MAX_WAIT);
			config.setTestOnBorrow(TEST_ON_BORROW);
			config.setTestWhileIdle(TEST_WHILE_IDLE);
			shardCommonPool = new ShardedJedisPool(config, listJedisShardInfo);
			logger.info("init   shardedpool  ok");

		} catch (Exception e) {
			logger.error("initialPool error", e);
		}
	}

	/**
	 * 从公用redis集群获取resource
	 * 
	 * @return
	 */
	public ShardedJedis getJedis() {
		try {
			if (shardCommonPool != null) {
				ShardedJedis resource = shardCommonPool.getResource();
				return resource;
			} else {
				return null;
			}
		} catch (Exception e) {
			logger.error("[ShardJedisUtil]->[getJedis] error: ", e);
			return null;
		}
	}

	/**
	 * 归还redis链接
	 * 
	 * @param jedis
	 */
	public void returnJedis(final ShardedJedis jedis) {
		if (jedis != null) {
			shardCommonPool.returnResource(jedis);
		}
	}

	/**
	 * 归还坏redis链接
	 * 
	 * @param jedis
	 */
	public void returnBrokenJedis(final ShardedJedis jedis) {
		if (jedis != null) {
			shardCommonPool.returnBrokenResource(jedis);
		}
	}

	/**
	 * 内部接口也是回调接口，只定义抽象方法
	 * 
	 * @author haoxw
	 * @since 2014/4/22
	 */
	public interface JedisCallback {
		Object execute(ShardedJedis jedis) throws Exception;
	}

	/**
	 * 具体动作 并自动返回连接 需要具体实现
	 * 
	 * @param callback
	 * @return
	 */
	public Object getResult(JedisCallback callback) {
		ShardedJedis jedis = getJedis();
		try {
			return callback.execute(jedis);
		} catch (Exception e) {
			logger.error("", e);
			returnBrokenJedis(jedis);
			throw new RuntimeException("Redis getResult exception", e);
		} finally {
			if (jedis != null)
				returnJedis(jedis);
		}
	}
}
